package Generic;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

import org.jfree.chart.*;
import org.jfree.chart.axis.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.renderer.xy.*;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

@SuppressWarnings({"serial","rawtypes"})
public class EAApplicationFrame2 extends JFrame implements ActionListener,WindowListener{

	private static final int DEFAULT_COLUMNS = 5;

	private JTextField populationSizeField;
	private JTextField numberOfGenerationsField;
	private JTextField crossoverRateField;
	private JTextField mutationRateField;

	private List<JTextField> additionalParameterFields;

	private Class eaClass;

	private JPanel standardParameterPanel;

	private JPanel additionalParameterPanel;

	private XYSeries maxSeries;         
	private XYSeries averageSeries;
	private XYSeries standardDeviationSeries;

	private List<XYSeries> additionalSeries;

	private JPanel sidePanel;

	private ChartPanel chartPanel;
	
	private JFreeChart chart;
	
	private JPanel bestIndividualPanel;

	private JPanel targetPanel;
	private JPanel individualPanel;

	public EAApplicationFrame2(Class eaClass) {
		super(eaClass.getName());
		
		addWindowListener( this);
		
		this.eaClass = eaClass;
		//setBounds(50, 50,800, 600);

		getContentPane().setLayout(new BoxLayout(getContentPane(),BoxLayout.X_AXIS));

		standardParameterPanel = new JPanel();
		standardParameterPanel.setLayout(new BoxLayout(standardParameterPanel,BoxLayout.Y_AXIS));

		populationSizeField = new JTextField(Integer.toString(EvolutionaryAlgorithm.DEFAULT_POPULATION_SIZE), DEFAULT_COLUMNS);
		populationSizeField.setHorizontalAlignment(JTextField.CENTER);
		standardParameterPanel.add(new JLabel("Population Size"));
		standardParameterPanel.add(populationSizeField);

		numberOfGenerationsField = new JTextField(Integer.toString(EvolutionaryAlgorithm.DEFAULT_NUMBER_OF_GENERATIONS), DEFAULT_COLUMNS);
		numberOfGenerationsField.setHorizontalAlignment(JTextField.CENTER);
		standardParameterPanel.add(new JLabel("Number of Generations"));
		standardParameterPanel.add(numberOfGenerationsField);

		crossoverRateField = new JTextField(Double.toString(EvolutionaryAlgorithm.DEFAULT_CROSSOVER_RATE), DEFAULT_COLUMNS);
		crossoverRateField.setHorizontalAlignment(JTextField.CENTER);
		standardParameterPanel.add(new JLabel("Crossover Rate"));
		standardParameterPanel.add(crossoverRateField);

		mutationRateField = new JTextField(Double.toString(EvolutionaryAlgorithm.DEFAULT_MUTATION_RATE), DEFAULT_COLUMNS);
		mutationRateField.setHorizontalAlignment(JTextField.CENTER);
		standardParameterPanel.add(new JLabel("Mutation Rate"));
		standardParameterPanel.add(mutationRateField);

		additionalParameterPanel = new JPanel();
		additionalParameterPanel.setLayout(new BoxLayout(additionalParameterPanel,BoxLayout.Y_AXIS));

		additionalParameterFields = new ArrayList<JTextField>();
		for(int i =0;i< EvolutionaryAlgorithm.additionalParameters.size(); i++)
		{
			JTextField textField = new JTextField(Double.toString(EvolutionaryAlgorithm.additionalParameterValues.get(i)),DEFAULT_COLUMNS);
			textField.setHorizontalAlignment(JTextField.CENTER);
			additionalParameterPanel.add(new JLabel(EvolutionaryAlgorithm.additionalParameters.get(i)));
			additionalParameterPanel.add(textField);
			additionalParameterFields.add(textField);
		}

		maxSeries = new XYSeries("Max Fitness");         
		averageSeries = new XYSeries("Average Fitness");
		standardDeviationSeries = new XYSeries("Standard Deviation");
		final XYSeriesCollection standardCollection = new XYSeriesCollection();
		standardCollection.addSeries(maxSeries);
		standardCollection.addSeries(averageSeries);
		standardCollection.addSeries(standardDeviationSeries);

		final NumberAxis standardAxis = new NumberAxis("Fitness");
		final XYPlot standardSubplot = new XYPlot(standardCollection, null, standardAxis,new StandardXYItemRenderer());

		List<XYPlot> additionalPlots = new ArrayList<XYPlot>();
		additionalSeries = new ArrayList<XYSeries>();
		for(String string : EvolutionaryAlgorithm.additionalStatisticNames)
		{
			XYSeries series = new XYSeries(string);
			additionalSeries.add(series);
			XYSeriesCollection collection = new XYSeriesCollection();
			collection.addSeries(series);
			NumberAxis axis = new NumberAxis(string);
			StandardXYItemRenderer rend = new StandardXYItemRenderer();
			rend.setSeriesPaint(0, Color.BLACK);
			XYPlot subplot = new XYPlot(collection, null, axis,rend);
			additionalPlots.add(subplot);
		}

		final CombinedDomainXYPlot plot = new CombinedDomainXYPlot(new NumberAxis("Generations"));
		plot.add(standardSubplot,1);
		for(XYPlot subplot : additionalPlots)plot.add(subplot);

		chart = new JFreeChart(eaClass.getName(),JFreeChart.DEFAULT_TITLE_FONT,plot,true);

		chartPanel = new ChartPanel(chart);
		chartPanel.setPreferredSize(new java.awt.Dimension(800, 500));

		JButton startButton = new JButton("Start!");
		startButton.addActionListener(this);

		JButton printButton = new JButton("Print!");
		printButton.addActionListener(this);

		JPanel buttonPanel = new JPanel();
		buttonPanel.setLayout(new BoxLayout(buttonPanel,BoxLayout.X_AXIS));

		bestIndividualPanel = new JPanel();
		bestIndividualPanel.setLayout(new BoxLayout(bestIndividualPanel,BoxLayout.Y_AXIS));
		
		sidePanel = new JPanel();
		sidePanel.setLayout(new BoxLayout(sidePanel,BoxLayout.Y_AXIS));
		sidePanel.add(standardParameterPanel);
		sidePanel.add(additionalParameterPanel);
		buttonPanel.add(startButton);
		buttonPanel.add(printButton);
		sidePanel.add(buttonPanel);
		
		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setViewportView(bestIndividualPanel);
		scrollPane.setPreferredSize(new Dimension(300,500));
		
		targetPanel = new JPanel();
		individualPanel = new JPanel();
		individualPanel.setLayout(new BoxLayout(individualPanel,BoxLayout.Y_AXIS));
		
		individualPanel.add(targetPanel);
		individualPanel.add(scrollPane);
		
		getContentPane().add(chartPanel);
		getContentPane().add(sidePanel);
		getContentPane().add(individualPanel);

		pack();
	}

	public void actionPerformed(ActionEvent event) {
		if(((JButton)event.getSource()).getText().equals("Start!"))
		{

			maxSeries.clear();
			averageSeries.clear();
			standardDeviationSeries.clear();
			
			bestIndividualPanel.removeAll();

			for(XYSeries series : additionalSeries)
			{
				series.clear();
			}

			sidePanel.setEnabled(false);

			EvolutionaryAlgorithm ea = null;

			for(int i = 0; i < EvolutionaryAlgorithm.additionalParameterValues.size(); i++)
			{
				EvolutionaryAlgorithm.additionalParameterValues.set(i,Double.parseDouble(additionalParameterFields.get(i).getText()));
			}

			try {
				ea = (EvolutionaryAlgorithm) eaClass.newInstance();
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}

			ea.initialize(Integer.parseInt(populationSizeField.getText()),
					Double.parseDouble(crossoverRateField.getText()),
					Double.parseDouble(mutationRateField.getText()));
			
			targetPanel.removeAll();
			targetPanel.add(ea.getTargetPanel());

			for(int i = 0; i < Integer.parseInt(numberOfGenerationsField.getText()); i++)
			{
				ea.iterateGeneration();

				maxSeries.add(i, ea.getMaxFitness());
				averageSeries.add(i, ea.getAverageFitness());
				standardDeviationSeries.add(i,ea.getStandardDeviation());
				for(XYSeries series : additionalSeries){
					series.add(i,ea.getAdditionalStatistic(series.getKey().toString()));
				}
				
				JPanel panel = new JPanel();
				panel.add(new JLabel(Integer.toString(i)+":    "));
				panel.add(ea.getBestIndividualPanel());
				bestIndividualPanel.add(panel);
				if(i%100==0)
					chartPanel.paint(chartPanel.getGraphics());
			}
			pack();
		}
		else{
			try 
			{
				ChartUtilities.saveChartAsJPEG(new File(eaClass.getName()+"_pop"+populationSizeField.getText()+"_cross"+crossoverRateField.getText()+"_mut"+mutationRateField.getText()+".jpg"), chart, this.getWidth(), this.getHeight());
			} catch (IOException e) 
			{
				e.printStackTrace();
			}
		}
	}

	@Override
	public void windowActivated(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowClosed(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowClosing(WindowEvent arg0) {
		// TODO Auto-generated method stub
		dispose();
		System.exit(0);
	}

	@Override
	public void windowDeactivated(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowDeiconified(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowIconified(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowOpened(WindowEvent arg0) {
		
	}

}
